﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Data.Common;

namespace Tilver.Data
{
    /// <summary>
    /// 数据库访问封装类
    /// </summary>
    public class DbAdoBase : IDbAdo
    {
        #region Constructs

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="commandText">SQL语句</param>
        /// <param name="commandType">操作类型，sql语句或存储过程</param>
        /// <param name="dataBase">数据库访问类</param>
        public DbAdoBase(string commandText, CommandType commandType, DbDataBase dataBase)
        {
            this.DataBase = dataBase;
            this.Command = dataBase.CreateCommand(commandText, commandType);
        }
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="commandText">SQL语句</param>
        /// <param name="connectionStringName">配置文件中的定义的数据库连接名称</param>
        public DbAdoBase(string commandText, string connectionStringName) : this(commandText, CommandType.Text, DbDataFactory.Create(connectionStringName)) { }
        /// <summary>
        /// 构造函数，默认使用配置文件中定义的数据库连接串名称（defaultDataBase）
        /// </summary>
        /// <param name="commandText">SQL语句</param>
        public DbAdoBase(string commandText) : this(commandText, CommandType.Text, DbDataFactory.Create()) { }
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="commandText">SQL语句</param>
        /// <param name="dataBase">数据库访问类</param>
        public DbAdoBase(string commandText, DbDataBase dataBase) : this(commandText, CommandType.Text, dataBase) { }

        #endregion

        #region IDbAdo 成员

        /// <summary>
        /// 数据库访问对象
        /// </summary>
        public DbDataBase DataBase
        {
            get;
            internal set;
        }
        /// <summary>
        /// DbCommand对象
        /// </summary>
        public CommandWrapper Command
        {
            get;
            internal set;
        }
        /// <summary>
        /// 执行查询语句并返回首行首列数据
        /// </summary>
        /// <param name="tm">数据库事务管理对象</param>
        /// <returns></returns>
        public object ExecuteScalar(TransactionManager tm = null)
        {
            return DataBase.ExecuteScalar(DataBase.CreateCommand(Command, tm));
        }
        /// <summary>
        /// 执行SQL语句并返回受影响的行数
        /// </summary>
        /// <param name="tm">数据库事务管理对象</param>
        /// <returns></returns>
        public int ExecuteNonQuery(TransactionManager tm = null)
        {
            return DataBase.ExecuteNonQuery(DataBase.CreateCommand(Command, tm));
        }
        /// <summary>
        /// 执行SQL语句并返回结果集
        /// </summary>
        /// <param name="tm">数据库事务管理对象</param>
        /// <returns></returns>
        public DbDataReader ExecuteReader(TransactionManager tm = null)
        {
            return DataBase.ExecuteReader(DataBase.CreateCommand(Command, tm));
        }
        /// <summary>
        /// 执行SQL语句并返回结果集
        /// </summary>
        /// <typeparam name="T">IDataReader对象映射的实体对象，T应该继承接口IRowMapper或使用DataColumnAttribute定义属性</typeparam>
        /// <param name="rowMapper">IDataReader对象到实体对象的映射方法，如果为null，则默认要求实体对象(T)使用DataColumnAttribute定义元数据，以便反射获取实体对象</param>
        /// <param name="tm">数据库事务管理对象</param>
        /// <returns></returns>
        public T ExecuteSingle<T>(Func<IDataReader, T> rowMapper = null, TransactionManager tm = null)
        {
            return this.ExecuteReader(tm).MapToSingle<T>(rowMapper);
        }
        /// <summary>
        /// 执行SQL语句并返回结果集(T)
        /// </summary>
        ///<typeparam name="T">IDataReader对象映射的实体对象，T应该继承接口IRowMapper或使用DataColumnAttribute定义属性</typeparam>
        /// <param name="rowMapper">IDataReader对象到实体对象的映射方法，如果为null，则默认要求实体对象(T)使用DataColumnAttribute定义元数据，以便反射获取实体对象</param>
        /// <param name="tm">数据库事务管理对象</param>
        /// <returns></returns>
        public IEnumerable<T> ExecuteMutil<T>(Func<IDataReader, T> rowMapper = null, TransactionManager tm = null)
        {
            return this.ExecuteReader(tm).MapToMutil<T>(rowMapper);
        }
        /// <summary>
        /// 执行SQL语句并返回结果集(T)
        /// </summary>
        ///<typeparam name="T">IDataReader对象映射的实体对象，T应该继承接口IRowMapper或使用DataColumnAttribute定义属性</typeparam>
        /// <param name="rowMapper">IDataReader对象到实体对象的映射方法，如果为null，则默认要求实体对象(T)使用DataColumnAttribute定义元数据，以便反射获取实体对象</param>
        /// <param name="tm">数据库事务管理对象</param>
        /// <returns></returns>
        public List<T> ExecuteList<T>(Func<IDataReader, T> rowMapper = null, TransactionManager tm = null)
        {
            return this.ExecuteReader(tm).MapToList<T>(rowMapper);
        }
        /// <summary>
        /// 执行SQL语句并返回DataTable对象
        /// </summary>
        /// <param name="tm">数据库事务管理对象</param>
        /// <returns></returns>
        public DataTable ExecuteDataTable(TransactionManager tm = null)
        {
            IDataReader dr = this.ExecuteReader(tm);
            DataTable table = new DataTable();
            table.Load(dr);
            dr.Close();
            return table;
        }

        /// <summary>
        /// 创建DbParameter对象
        /// </summary>
        /// <param name="name"></param>
        /// <param name="value"></param>
        /// <param name="dbType"></param>
        /// <param name="size"></param>
        /// <param name="direction"></param>
        /// <returns></returns>
        public DbParameter CreateParameter(string name, object value, DbType dbType = DbType.String, int size = 0, ParameterDirection direction = ParameterDirection.Input)
        {
            return DataBase.CreateParameter(name, value, dbType, size, direction);
        }

        #endregion

        #region 参数处理

        /// <summary>
        /// 添加多个DbParameter参数
        /// </summary>
        /// <param name="parameters"></param>
        /// <returns></returns>
        public DbAdoBase AddParameters(IEnumerable<DbParameter> parameters)
        {
            foreach (var param in parameters)
            {
                Command.Parameters.Add(param);
            }
            return this;

        }
        /// <summary>
        /// 添加DbParameter参数
        /// </summary>
        /// <param name="param">DbParameter对象</param>
        /// <returns></returns>
        public DbAdoBase AddParameter(DbParameter param)
        {
            Command.Parameters.Add(param);
            return this;
        }

        
        /// <summary>
        /// 添加DbParameter参数
        /// </summary>
        /// <param name="name">参数名称</param>
        /// <param name="dbType">参数的 DbType</param>
        /// <param name="size">列中数据的最大大小（以字节为单位）</param>
        /// <returns></returns>
        public DbAdoBase AddParameter(string name, object value, DbType dbType = DbType.String, int size = 0, ParameterDirection direction = ParameterDirection.Input)
        {
            DbParameter param = CreateParameter(name, value, dbType, size, direction);
            Command.Parameters.Add(param);
            return this;
        }

        /// <summary>
        /// 添加DbParameter参数和值
        /// </summary>
        /// <param name="name">参数名称</param>
        /// <param name="value">参数的值</param>
        /// <param name="dbType">参数的 DbType</param>
        /// <param name="size">列中数据的最大大小（以字节为单位）</param>
        /// <returns></returns>
        public DbAdoBase AddInParameter(string name, object value, DbType dbType = DbType.String, int size = 0)
        {
            DbParameter param = CreateParameter(name, value, dbType, size, ParameterDirection.Input);
            Command.Parameters.Add(param);
            return this;
        }

        /// <summary>
        /// 添加DbParameter参数和值
        /// </summary>
        /// <param name="name">参数名称</param>
        /// <param name="value">参数的值</param>
        /// <param name="dbType">参数的 DbType</param>
        /// <param name="size">列中数据的最大大小（以字节为单位）</param>
        /// <returns></returns>
        public DbAdoBase AddOutParameter(string name, object value, DbType dbType = DbType.String, int size = 0)
        {
            DbParameter param = CreateParameter(name, value, dbType, size, ParameterDirection.Output);
            Command.Parameters.Add(param);
            return this;
        }
        /// <summary>
        /// 添加DbParameter参数和值
        /// </summary>
        /// <param name="name">参数名称</param>
        /// <param name="value">参数的值</param>
        /// <param name="dbType">参数的 DbType</param>
        /// <param name="size">列中数据的最大大小（以字节为单位）</param>
        /// <returns></returns>
        public DbAdoBase AddInOutParameter(string name, object value, DbType dbType = DbType.String, int size = 0)
        {
            DbParameter param = CreateParameter(name, value, dbType, size, ParameterDirection.InputOutput);
            Command.Parameters.Add(param);
            return this;
        }
        
        /// <summary>
        /// 清除所有定义的参数集合
        /// </summary>
        public void ClearParameters()
        {
            Command.Parameters.Clear();
        }
        ///// <summary>
        ///// 设置DbParameter参数的值
        ///// </summary>
        ///// <param name="name">参数名称</param>
        ///// <param name="value">参数的值</param>
        ///// <returns></returns>
        //public DbAdoBase SetParameterValue(string name, object value)
        //{
        //    Command.Parameters[name].Value = value;
        //    return this;
        //}
        ///// <summary>
        ///// 获取DbParameter参数的值
        ///// </summary>
        ///// <param name="name">参数名称</param>
        ///// <returns></returns>
        //public object GetParameterValue(string name)
        //{
        //    return Command.Parameters[name].Value;
        //}
        #endregion
    }
}
